package io.awen.modules.sign.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import io.awen.common.exception.RRException;
import io.awen.common.utils.DateUtils;
import io.awen.common.utils.PageUtils;
import io.awen.common.utils.Query;
import io.awen.config.MqttConfig;
import io.awen.modules.sign.StatusConstants;
import io.awen.modules.sign.dao.SignCarDispatchDao;
import io.awen.modules.sign.entity.*;
import io.awen.modules.sign.qo.SignCarDispatchQo;
import io.awen.modules.sign.service.*;
import io.awen.modules.sys.entity.SysUserEntity;
import io.awen.modules.sys.qo.SysUserQo;
import io.awen.modules.sys.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


@Service("signCarDispatchService")
@Slf4j
public class SignCarDispatchServiceImpl extends ServiceImpl<SignCarDispatchDao, SignCarDispatchEntity> implements SignCarDispatchService {

    @Autowired
    private SignContainerService signContainerService;
    @Autowired
    private SignContainerAlarmService signContainerAlarmService;
    @Autowired
    private SignTaskService signTaskService;
    @Autowired
    private SignCarService signCarService;

    @Autowired
    private MqttConfig mqttConfig;

    @Autowired
    private SysUserService sysUserService;

    private final static Gson gson = new Gson();

    @Override
    public PageUtils queryPage(SignCarDispatchQo qo) {
        IPage<SignCarDispatchEntity> page = this.page(
                new Query<SignCarDispatchEntity>().getPage(qo),
                new QueryWrapper<SignCarDispatchEntity>().lambda()
                        .eq(qo.getProductContainerId() != null, SignCarDispatchEntity::getProductContainerId, qo.getProductContainerId())
                        .eq(qo.getCtUnitId() != null, SignCarDispatchEntity::getCtUnitId, qo.getCtUnitId())
                        .ne(SignCarDispatchEntity::getDispatchType, "2")
                        .ge(qo.getStartTime() != null, SignCarDispatchEntity::getCreateTime, qo.getStartTime())
                        .le(qo.getEndTime() != null, SignCarDispatchEntity::getCreateTime, qo.getEndTime())
                        .eq(StringUtils.isNotBlank(qo.getStatus()), SignCarDispatchEntity::getStatus, qo.getStatus())
                        .eq(StringUtils.isNotBlank(qo.getDispatchType()), SignCarDispatchEntity::getDispatchType, qo.getDispatchType())
                        .orderByDesc(SignCarDispatchEntity::getId)
        );

        for (SignCarDispatchEntity entity : page.getRecords()) {
            List<SignTaskEntity> taskList = signTaskService.list(
                    new QueryWrapper<SignTaskEntity>().lambda()
                            .eq(SignTaskEntity::getDispatchId, entity.getId())
                            .orderByAsc(SignTaskEntity::getId)
            );

            for(SignTaskEntity entity1:taskList){
                Long dispatchCarId = entity1.getDispatchCarId();
                SignCarEntity car = signCarService.getById(dispatchCarId);
                if(car!=null){
                    Long driverId = car.getDriverId();
                    SysUserEntity user = sysUserService.getById(driverId);
                    entity1.setUser(user);
                }
            }

            entity.setTaskList(taskList);
        }





        return new PageUtils(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void autoDispatch(SignContainerEntity container, SignContainerAlarmEntity alarm) {
        SignCarDispatchEntity dispatch = new SignCarDispatchEntity();
        dispatch.setAlarmId(alarm.getId());
        dispatch.setProductContainerId(container.getId());
        dispatch.setCtUnitId(container.getCtUnitId());
        dispatch.setDispatchType("0");
        dispatch.setResidueCalCount(container.getInitCalCount());
        dispatch.setName(container.getName() + "-收运调度[" + DateUtils.format(alarm.getAlarmTime(), "yyyy年MM月dd日HH时mm分") + "]");
        save(dispatch);

        if (dispatch.getResidueCalCount() == 0) {
            // 通知管理员手动给该调度下发任务
            log.error("通知管理员手动给该调度下发任务");

            SysUserQo qo = new SysUserQo();
//            qo.setCtUnitId(dispatch.getCtUnitId());
            qo.setRoleName("收运单位超级管理员");
            List<SysUserQo> userList = sysUserService.queryByRoleName(qo);
            for (SysUserQo entity : userList) {
                mqttConfig.getMqttPushClient().publish(1, false, "dispatch_" + entity.getUserId(), gson.toJson(dispatch));
            }
//            providerClient.publish(1, false, "topic1", gson.toJson(dispatch));
        } else {
            // 计算最近车辆，指派任务
            signTaskService.autoTask(container, dispatch);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void manualDispatch(SignCarDispatchEntity dispatch) {
        if (dispatch.getProductContainerId() == null) {
            throw new RRException("请选择容器");
        }
        SignContainerEntity container = signContainerService.findContainer(dispatch.getProductContainerId());
        if (dispatch.getResidueCalCount() == 0) {
            if (dispatch.getTask() == null || dispatch.getTask().getDispatchCarId() == null) {
                throw new RRException("请选择执行收运任务的车辆");
            } else if (dispatch.getTask().getDispatchCarId() != null) {
                SignCarEntity car = signCarService.findCar(dispatch.getTask().getDispatchCarId());
                if (!car.getFleetId().equals(container.getCtFleetId())) {
                    throw new RRException("污水池绑定的收运单位与车辆不匹配");
                } else if (StatusConstants.CAR_STATUS_STOP.equals(car.getStatus())) {
                    throw new RRException("车辆暂时不接收运任务");
                }
            }
        }

//        if (dispatch.getSyWeight() == null) {
//            throw new RRException("请输入收运量");
//        }
        dispatch.setSyWeight(0.);

        // 发起调度的人 是否拥有容器权限，是否与司机是同一个收运单位
        dispatch.setCtUnitId(container.getCtUnitId());

        dispatch.setName(container.getName() + "-收运调度[" + DateUtils.format(new Date(), "yyyy年MM月dd日HH时mm分") + "]");
        //创建字符串taskStatus
        String taskStatus = null;

        if(dispatch.getDispatchType()==null){
            dispatch.setDispatchType("1");
            taskStatus = StatusConstants.TASK_STATUS_WAITED;
        } else if (dispatch.getDispatchType().equals("2")) {
            dispatch.setDispatchType("2");
            taskStatus = StatusConstants.TASK_STATUS_PROCESSING;
        }
        save(dispatch);

        if (dispatch.getResidueCalCount() == 0) {
            SignTaskEntity task = new SignTaskEntity();
            task.setDispatchId(dispatch.getId());
            task.setCtUnitId(dispatch.getCtUnitId());
            task.setProductionContainerId(dispatch.getProductContainerId());
            task.setDispatchCarId(dispatch.getTask().getDispatchCarId());
            task.setStartTime(new Date());
            task.setStatus(taskStatus);

            task.setName(container.getName() + "-收运任务[" + DateUtils.format(task.getStartTime(), "yyyy年MM月dd日HH时mm分") + "]");

            signTaskService.save(task);

            dispatch.setCurTaskId(task.getId());
            dispatch.setStatus(task.getStatus());
            updateById(dispatch);

            SignCarEntity car = signCarService.findCar(dispatch.getTask().getDispatchCarId());
            mqttConfig.getMqttPushClient().publish(1, false, "task_" + car.getDriverId(), gson.toJson(task));
        } else {
            // 计算最近车辆，指派任务
            signTaskService.autoTask(dispatch);
        }
    }

    @Override
    public List<SignCarDispatchEntity> waitManualList(SignCarDispatchQo qo) {
//        SysUserEntity user = ShiroUtils.getUserEntity();
        List<String> statusList = new ArrayList<String>(2);
        statusList.add(StatusConstants.TASK_STATUS_REJECT);
        statusList.add(StatusConstants.TASK_STATUS_DISPATCH);
        List<SignCarDispatchEntity> list = list(
                new QueryWrapper<SignCarDispatchEntity>().lambda()
                        .eq(qo.getCtUnitId() != null, SignCarDispatchEntity::getCtUnitId, qo.getCtUnitId())
                        .eq(qo.getProductContainerId() != null, SignCarDispatchEntity::getProductContainerId, qo.getProductContainerId())
                        .eq(qo.getDispatchType() != null, SignCarDispatchEntity::getDispatchType, qo.getDispatchType())
                        .in(SignCarDispatchEntity::getStatus, statusList)
                        .orderByDesc(SignCarDispatchEntity::getId)
        );

//        for (SignCarDispatchEntity entity : list) {
//            if (entity.getProductContainerId() != null) {
//                entity.setContainer(signContainerService.getById(entity.getProductContainerId()));
//            }
//            if (entity.getAlarmId() != null) {
//                entity.setAlarm(signContainerAlarmService.getById(entity.getAlarmId()));
//            }
//        }

        return list;
    }

    @Override
    public int total(SignCarDispatchQo qo) {
        int count = this.count(
                new QueryWrapper<SignCarDispatchEntity>().lambda()
                        .eq(qo.getCtUnitId() != null, SignCarDispatchEntity::getCtUnitId, qo.getCtUnitId())
                        .ge(qo.getStartTime() != null, SignCarDispatchEntity::getCreateTime, qo.getStartTime())
                        .le(qo.getEndTime() != null, SignCarDispatchEntity::getCreateTime, qo.getEndTime())
                        .eq(StringUtils.isNotBlank(qo.getStatus()), SignCarDispatchEntity::getStatus, qo.getStatus())
                        .eq(StringUtils.isNotBlank(qo.getDispatchType()), SignCarDispatchEntity::getDispatchType, qo.getDispatchType())
        );
        return count;
    }

    @Override
    public Double weightTotal(SignCarDispatchQo qo) {
        return this.baseMapper.weightTotal(qo.getCtUnitId(), qo.getStartTime(), qo.getEndTime(), qo.getDispatchType());
    }


}